/**  
* @author xuguofei
* @date 2018年12月24日
* @version 1.0
*/
package cn.xu.framework.common.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.*;

public class CSVUtil {
	
	/**
	 * @Title: createCSVFile   
	 * @author: xuguofei
	 * @Description: CSV文件生成方法 
	 * @param: @param head
	 * @param: @param fieldDetailNames
	 * @param: @param read
	 * @param: @param outPutFullPath
	 * @param: @param T
	 * @param: @param excludeCloums
	 * @param: @param page
	 * @param: @param size
	 * @param: @param isPager 是否分页
	 * @param: @return
	 * @param: @throws Exception      
	 * @return: File      
	 * @throws
	 */
    public static File createCSVFile(List<String> head, String[] fieldDetailNames, CSVBaseDataRead read,
            String outPutFullPath, Class T, List<String> excludeCloums, int page, int size, boolean isPager) throws Exception {

        File csvFile = null;
        BufferedWriter csvWtriter = null;
        try {
            csvFile = new File(outPutFullPath);
            File parent = csvFile.getParentFile();
            if (parent != null && !parent.exists()) {
                parent.mkdirs();
            }
            csvFile.createNewFile();
            // GB2312使正确读取分隔符","
            csvWtriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
                    csvFile), "GBK"), 1024);
            // 写入文件头部
            writeHead(head, csvWtriter);
            List datas = read.getData(page, size);
            if(isPager){
            	while (datas!=null&&datas.size()>0) {
                	// 写入文件内容
                    for (Object row : datas) {
                        writeRow(fieldDetailNames, row, T, csvWtriter, excludeCloums);
                    }
                    page++;
                	datas = read.getData(page, size);
    			}
            }else{
            	if (datas!=null&&datas.size()>0) {
                	// 写入文件内容
                    for (Object row : datas) {
                        writeRow(fieldDetailNames, row, T, csvWtriter, excludeCloums);
                    }
    			}
            }
            
            csvWtriter.flush();
        } finally {
            try {
                csvWtriter.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return csvFile;
    }

    /**
     * @Title: writeRow   
     * @author: xuguofei
     * @Description: 写一行数据方法
     * @param: @param fieldDetailNames
     * @param: @param row
     * @param: @param csvWriter
     * @param: @param excludeCloums
     * @param: @throws IOException      
     * @return: void      
     * @throws
     */
    private static void writeRow(String[] fieldDetailNames, Object row, Class T, BufferedWriter csvWriter, List<String> excludeCloums) throws Exception {
    	List<Object> rowData = new ArrayList<>();
    	for (String field : fieldDetailNames) {
    		if(excludeCloums!=null&&excludeCloums.contains(field)){
    			continue;
    		}
    		rowData.add(getData(T, row, field));
		}
    	for (Object data : rowData) {
            StringBuffer sb = new StringBuffer();
            String rowStr = sb.append("\"").append(data==null?"":data).append("\"\t,").toString();
            csvWriter.write(rowStr);
        }
        csvWriter.newLine();
    }
    
    private static Object getData(Class T, Object row, String fieldName) throws Exception {
    	if(T.getSimpleName().equals("HashMap")){
    		Map<String, Object> map = (Map<String, Object>) row;
    		return map.get(fieldName)==null?map.get(fieldName.toUpperCase()):map.get(fieldName);
    	}else{
    		Field[] fields = getAllFields(T);
    		for (int j=0;j<fields.length;j++) {
				Field f=fields[j];
				f.setAccessible(true);
				//只操作指定的字段名
				if(fieldName.equals(f.getName())){
					Object fieldValue = getGetMethod(row, fieldName);
					//调用get方法取值
//							System.out.println(f.getName()+":"+fieldValue.toString());
					if(fieldValue!=null){
						if("weight".equals( fieldName )){
							DecimalFormat decimalFormat1=new DecimalFormat("0.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
							fieldValue =decimalFormat1.format(fieldValue);
						}

						if("piece".equals( fieldName )){
							DecimalFormat decimalFormat1=new DecimalFormat("0.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
							fieldValue =decimalFormat1.format(fieldValue);
						}
						//判断是否日期类型
						if("java.util.Date".equals(f.getType().getName())){
							String dateTemp=DateFormatUtils.format((Date)fieldValue, "yyyy/MM/dd HH:mm:ss");
							return dateTemp;
						}else{
							return fieldValue.toString();
						}
					}else{
						return "";
					}
				}else{
					continue;
				}
    		}
    	}
		return null;
	}

    public static Field[] getAllFields(Class clazz){
	  List<Field> fieldList = new ArrayList<Field>();
	  while (clazz != null){
	    fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
	    clazz = clazz.getSuperclass();
	  }
	  Field[] fields = new Field[fieldList.size()];
	  fieldList.toArray(fields);
	  return fields;
	}

    /**
	 * 根据属性，获取get方法
	 * @param ob 对象
	 * @param name 属性名
	 * @return
	 * @throws Exception
	 */
	public static Object getGetMethod(Object ob , String name)throws Exception{
		Method[] m = ob.getClass().getMethods();
		for(int i = 0;i < m.length;i++){
			if(("get"+name).toLowerCase().equals(m[i].getName().toLowerCase())){
				return m[i].invoke(ob);
			}
		}
		return null;
	}
	
	/**
     * 写表格头部方法
     * @param row
     * @param csvWriter
     * @throws IOException
     */
    private static void writeHead(List<String> row, BufferedWriter csvWriter) throws IOException {
        // 写入文件头部
        for (Object data : row) {
            StringBuffer sb = new StringBuffer();
            String rowStr = sb.append("\"").append(data==null?"":data).append("\",").toString();
            csvWriter.write(rowStr);
        }
        csvWriter.newLine();
    }
}
